package ev.agent;

import ev.utility.*;
import ev.space.*;
import ev.traffic.*;

import java.util.Random;
import swarm.collections.List;
import swarm.collections.Index;

public class RanOwner implements Owner {
	public static final int RANDOM_MODE = 0;
	public static final int PRICE_APT_MODE = 1;
	public static final int DISTANCE_APT_MODE = 2;
	public static final int COMPOUND_MODE = 3;
	private Car car;
	private int chooseMode;
	private double satisfy;
	private java.util.List<Double> satisfyList;

	public RanOwner(Car car, int chooseMode) {
		this.car = car;
		this.chooseMode = chooseMode;
		//为进行算例分析，暂时改为仅考虑路程，记得改回来
//		this.chooseMode = RANDOM_MODE;
		satisfyList = new java.util.ArrayList<Double>();
	}

	public void chooseSub() {
		List subList = SubSpace.subList;
		int nodeNum = this.car.getNode().getNum();
		Substation sub = null;
		switch (chooseMode) {
		case RANDOM_MODE:// 随机选取
			int i = new Random().nextInt(subList.getCount());
			sub = (Substation) subList.atOffset(i);
			this.car.setSub(sub);
			break;
		case PRICE_APT_MODE:// 优先根据电价选择
			SwarmUtils.sortSubList(nodeNum, 0, subList);
			sub = (Substation) subList.getFirst();
			this.car.setSub(sub);
			break;
		case DISTANCE_APT_MODE:// 优先根据距离选择
			SwarmUtils.sortSubList(nodeNum, 1, subList);
			sub = (Substation) subList.getFirst();
			this.car.setSub(sub);
			break;
		case COMPOUND_MODE:// 综合考虑
			SwarmUtils.sortSubList(nodeNum, 2, subList);
			sub = (Substation) subList.getFirst();
			this.car.setSub(sub);
			break;
		}
		int xPos = sub.getXpos();
		int yPos = sub.getYpos();
		int destNum = CitySpace.getNodes(xPos, yPos).getNum();
		int startPoint = this.car.getNode().getNum();
		if (startPoint == destNum) {
			// 当前节点有充电站，不用行驶，直接到达
			this.car.setState(Car.FAST_CHARGE);
		}
		// 设定行驶路线
		this.car.setRoadLine(LineDecision.getRoadLine(startPoint, destNum));
	}

	public boolean ifChoose() {
		if (this.car.getSub() != null) {
			return false;
		}
//		float price = ((Substation) SubSpace.subList.getFirst()).getPrice();
		float price = Substation.getRegPrice();
//		float price = 0.4f;
		if (price < 0.4f && this.car.getSoc() <= 0.6f) {
			return true;
		} else if (price > 1 && this.car.getSoc() <= 0.2f) {
			return true;
		} else if (price >= 0.4f && price <= 1 && this.car.getSoc() <= 0.3f) {
			return true;
		} else {
			return false;
		}
	}

	public void changeState() {
		int state = this.car.getState();
		if (state == Car.STOP) {
			double hh = (double) TimeCal.hh;
			double chance = 0;
			Random ran = new Random();
			if (hh <= 8) {
				chance = (1 / 16) * hh + 0.1;
			} else if (hh >= 20) {
				chance = 0.6 - (1 / 8) * (24 - hh);
			} else {
				chance = 0.6;
			}
			if (ran.nextDouble() < chance) {
				this.car.setState(Car.RUNNING);
			}
		}
	}

	public void setMode(int chooseMode) {
		this.chooseMode = chooseMode;
	}

	public int getMode() {
		return this.chooseMode;
	}

	public double getSatisfy() {
		if (this.satisfyList == null || this.satisfyList.size() == 0) {
			return 0;
		}
		double result = 0;
		for (double d : this.satisfyList) {
			result += d;
		}
		result /= this.satisfyList.size();
		return result;
	}

	public void calSatisfy() {
		RanCar rc = (RanCar) car;
		int waitTime = rc.getWaitTime();
		double chargePrice = rc.getChargePrice();
		int length = this.car.getRoadLine().size();
		int distance = 0;
		if (length != 0) {
			int start = this.car.getRoadLine().get(0);
			int end = this.car.getRoadLine().get(length - 1);
			distance = LineDecision.getLength(start, end);
		}
		double wSatisfy = 40 * (Owner.ACCEPT_WAITTIME - waitTime)
				/ (Owner.ACCEPT_WAITTIME - Owner.SATISFY_WAITTIME) + 60;
		double cSatisfy = 40 * (Owner.ACCEPT_PRICE - chargePrice)
				/ (Owner.ACCEPT_PRICE - Owner.SATISFY_PRICE) + 60;
		double dSatisfy = 40 * (Owner.ACCEPT_DISTANCE - distance)
				/ (Owner.ACCEPT_DISTANCE - Owner.SATISFY_DISTANCE) + 60;
		if (wSatisfy > 100) {
			wSatisfy = 100;
		} else if (wSatisfy < 0) {
			wSatisfy = 0;
		}
		if (cSatisfy > 100) {
			cSatisfy = 100;
		} else if (cSatisfy < 0) {
			cSatisfy = 0;
		}
		if (dSatisfy > 100) {
			dSatisfy = 100;
		} else if (dSatisfy < 0) {
			dSatisfy = 0;
		}
		this.satisfy = (wSatisfy + cSatisfy + dSatisfy) / 3;
		rc = null;
		this.satisfyList.add(this.satisfy);
	}
}
